home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / AX25.C < prev    next >
C/C++ Source or Header  |  1990-10-06  |  14KB  |  480 lines

  1. /* Low level AX.25 frame processing - address header */
  2.  
  3. #include <stdio.h>
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "iface.h"
  7. #include "timer.h"
  8. #include "arp.h"
  9. #include "slip.h"
  10. #include "ax25.h"
  11. #include "lapb.h"
  12. #include <ctype.h>
  13.  
  14. char axbdcst[AXALEN];    /* Broadcast address (QST-0), network format */
  15. int digipeat = 1;    /* Controls single-band standard digipeating */
  16. struct mbuf *axloopq = NULLBUF; /* Loopback queue for AX.25 packets */
  17.  
  18. /* Send IP datagrams across an AX.25 link */
  19. int
  20. ax_send(bp,interface,gateway,precedence,delay,throughput,reliability)
  21. struct mbuf *bp;
  22. struct interface *interface;
  23. int32 gateway;
  24. char precedence;
  25. char delay;
  26. char throughput;
  27. char reliability;
  28. {
  29.     char *hw_addr,*res_arp();
  30.     struct ax25_cb *axp,*find_ax25(),*open_ax25();
  31.     struct ax25 addr;
  32.     struct ax25_addr destaddr;
  33.     struct mbuf *tbp;
  34.     extern int16 axwindow;
  35.     void ax_incom();
  36.     int16 size,bsize,seq;
  37.  
  38.     if((hw_addr = res_arp(interface,ARP_AX25,gateway,bp)) == NULLCHAR)
  39.         return 0;    /* Wait for address resolution */
  40.  
  41.     if(delay || (!reliability && !(interface->flags & IF_CONNECT_MODE))){
  42.         /* Use UI frame */
  43.         return (*interface->output)(interface,hw_addr,
  44.             interface->hwaddr,PID_FIRST|PID_LAST|PID_IP,bp);
  45.     }
  46.     /* Reliability is needed; use I-frames in AX.25 connection */
  47.     memcpy(destaddr.call,hw_addr,ALEN);
  48.     destaddr.ssid = hw_addr[ALEN];
  49.  
  50.     if((axp = find_ax25(&destaddr,(struct ax25_addr *)interface->hwaddr)) == NULLAX25 ||
  51.         (axp->state != CONNECTED && axp->state != SETUP)){
  52.         /* Open a new connection or reinitialize the old one */
  53.         atohax25(&addr,hw_addr,(struct ax25_addr *)interface->hwaddr);
  54.         axp = open_ax25(&addr,axwindow,ax_incom,NULLVFP,NULLVFP,interface,(char *)0);
  55.         if(axp == NULLAX25){
  56.             free_p(bp);
  57.             return -1;
  58.         }
  59.     }
  60.     /* If datagram is too big for one frame, send all but the last with
  61.      * the extension PID. Note: the copy to a new buf is necessary because
  62.      * AX.25 may continue retransmitting the frame after a local TCB has
  63.      * gone away, and using the buf directly would cause heap garbage to be
  64.      * transmitted. Besides, nobody would ever use AX.25 anywhere
  65.      * high performance is needed anyway...
  66.      */
  67.     bsize = len_mbuf(bp);
  68.     seq = 0;
  69.     while(bsize != 0){
  70.         size = min(bsize,axp->paclen);
  71.         /* Allocate buffer, allowing space for PID */
  72.         if((tbp = alloc_mbuf(size + 1)) == NULLBUF)
  73.             break;        /* out of memory! */
  74.         *tbp->data = PID_IP;
  75.         if(seq++ == 0)
  76.             *tbp->data |= PID_FIRST;    /* First in sequence */
  77.         if(size == bsize)
  78.             *tbp->data |= PID_LAST;        /* That's all of it */
  79.         /* else more to follow */
  80.  
  81.         tbp->cnt = 1;
  82.         tbp->cnt += pullup(&bp,tbp->data + 1,size);
  83.         send_ax25(axp,tbp);
  84.         bsize -= size;
  85.     }
  86.     free_p(bp);    /* Shouldn't be necessary */
  87.     return 0;
  88. }
  89. /* Add AX.25 link header and send packet.
  90.  * Note that the calling order here must match ec_output
  91.  * since ARP also uses it.
  92.  */
  93. ax_output(interface,dest,source,pid,data)
  94. struct interface *interface;
  95. char *dest;        /* Destination AX.25 address (7 bytes, shifted) */
  96.             /* Also includes digipeater string */
  97. char *source;        /* Source AX.25 address (7 bytes, shifted) */
  98. char pid;        /* Protocol ID */
  99. struct mbuf *data;    /* Data field (follows PID) */
  100. {
  101.     struct mbuf *abp,*cbp,*htonax25();
  102.     struct ax25 addr;
  103.  
  104.     /* Allocate mbuf for control and PID fields, and fill in */
  105.     if((cbp = pushdown(data,2)) == NULLBUF){
  106.         free_p(data);
  107.         return -1;
  108.     }
  109.     cbp->data[0] = UI;
  110.     cbp->data[1] = pid;
  111.  
  112.     atohax25(&addr,dest,(struct ax25_addr *)source);
  113.     if((abp = htonax25(&addr,cbp)) == NULLBUF){
  114.         free_p(cbp);    /* Also frees data */
  115.         return -1;
  116.     }
  117.     /* This shouldn't be necessary because redirection has already been
  118.      * done at the IP router layer, but just to be safe...
  119.      */
  120.     if(interface->forw != NULLIF)
  121.         return (*interface->forw->raw)(interface->forw,abp);
  122.     else
  123.         return (*interface->raw)(interface,abp);
  124. }
  125. /* Process incoming AX.25 packets.
  126.  * After optional tracing, the address field is examined. If it is
  127.  * directed to us as a digipeater, repeat it.  If it is addressed to
  128.  * us or to QST-0 or NODES-0, kick it upstairs depending on the protocol ID.
  129.  */
  130. int
  131. ax_recv(interface,bp)
  132. struct interface *interface;
  133. struct mbuf *bp;
  134. {
  135.     void arp_input();
  136.     int ip_route();
  137.     struct ax25_addr addr,*ap;
  138.     struct mbuf *htonax25(),*hbp;
  139.     struct ax25 hdr;
  140.     register struct ax25_cb *axp;
  141.     struct ax25_cb *find_ax25(),*cr_ax25();
  142.     register struct ax25_call *axc;
  143.     struct ax25_call *axd;
  144.     int timerscale,setdigi;
  145.     extern int16 t1init,t2init,t3init,t4init;
  146.  
  147.     /* Pull header off packet and convert to host structure */
  148.     if(ntohax25(&hdr,&bp) < 0){
  149.         /* Something wrong with the header */
  150.         free_p(bp);
  151.         return;
  152.     }
  153.     /* Update the users liatifor persistence calculation */
  154.     upd_nusers(interface,hdr.source.call);
  155.     /* Update the MHEARD liatifor this interface */
  156.     if(interface->mheard != 0){    /* first check if we have to keep it */
  157.         updmheard(interface,1,&hdr); /* update the liat */
  158.     }
  159.     /* check source address. it must NOT appear in the exclude liat */
  160.     ASSIGN(addr,hdr.source);    /* get the source address */
  161.     addr.ssid = 0;            /* discard the SSID */
  162.     if((axc = find_axcall(ax25_excl,&addr)) != NULLAXCALL &&
  163.         ((axc->flags & MULTI_IF) || axc->interface == interface)) {
  164.         free_p(bp);
  165.         return;
  166.     }
  167.     timerscale = hdr.ndigis + 1;    /* default scaling of timer values */
  168.  
  169.     /* Scan, looking for our call in the repeater fields, if any.
  170.      * Repeat appropriate packets.
  171.      */
  172.     for(ap = &hdr.digis[0]; ap < &hdr.digis[hdr.ndigis]; ap++){
  173.         if(ap->ssid & REPEATED)
  174.         continue;    /* Already repeated */
  175.         /* Check if packet is directed to us as a digipeater */
  176.         if((axc = find_axcall(ax25_digi,ap)) != NULLAXCALL){
  177.         /* check dest address. it must NOT appear in the exclude liat */
  178.         ASSIGN(addr,hdr.dest);    /* get the dest address */
  179.         addr.ssid = 0;        /* discard the SSID */
  180.         if((axd = find_axcall(ax25_excl,&addr)) != NULLAXCALL &&
  181.             ((axd->flags & MULTI_IF) ||
  182.              axd->interface == interface || axd->interface == axc->interface)) {
  183.             free_p(bp);
  184.             return;        /* if any doubt, refuse it */
  185.         }
  186.         switch (axc->mode)    /* check the digi mode */
  187.         {
  188.         case DIGIPEAT:        /* bare digipeater */
  189.             if (axc->interface == interface){ /* this band? */
  190.             if (!digipeat)    /* in-band digi disabled? */
  191.                 break;    /* throw it away */
  192.             } else {        /* not "home", gateway request */
  193.             if (axc->flags & DIGIGATEWAY &&
  194.                 (axd = find_axcall(ax25_digi,interface->hwaddr))
  195.                 != NULLAXCALL &&
  196.                  axd->mode == DIGIPEAT &&
  197.                  axd->flags & DIGIGATEWAY){
  198.                  /* swap callsign and interface */
  199.                  ASSIGN(*ap,*((struct ax25_addr *) interface->hwaddr));
  200.                  interface = axc->interface;
  201.             } else {
  202.                 break;    /* gateway conditions not fulfilled... */
  203.             }
  204.             }
  205.  
  206.             /* kick it back out */
  207.             ap->ssid |= REPEATED;
  208.             if((hbp = htonax25(&hdr,bp)) != NULLBUF){
  209.             if(interface->forw != NULLIF)
  210.                 (*interface->forw->raw)(interface->forw,hbp);
  211.             else
  212.                 (*interface->raw)(interface,hbp);
  213.             tnc2_kissrcv(interface,&hdr,bp,4);
  214.             bp = NULLBUF;
  215.             }
  216.             break;
  217.  
  218.         case DIGICONNECT:    /* digipeater simulating connection */
  219.             if ((axc->flags & MULTI_IF) ||
  220.             axc->interface == interface ||
  221.             (axc->flags & DIGIGATEWAY)){
  222.             /* address is okay */
  223.             if (bp != NULLBUF){
  224.                 timerscale = (int) (ap - &hdr.digis[0]) + 1;
  225.                 goto for_us;/* handle as if addressed to us */
  226.             }
  227.             }
  228.             break;
  229.         }
  230.         }
  231.         tnc2_kissrcv(interface,&hdr,bp,4);
  232.         free_p(bp);            /* Dispose if not forwarded */
  233.         return;
  234.     }
  235.     /* Packet has passed all repeaters, now look at destination */
  236.     if((axc = find_axcall(ax25_call,&hdr.dest)) == NULLAXCALL ||
  237.         !((axc->flags & MULTI_IF) || axc->interface == interface)) {
  238.         /* Not for us, or wrong interface for this callsign */
  239.         tnc2_kissrcv(interface,&hdr,bp,3);
  240.         free_p(bp);
  241.         return;
  242.     }
  243.  
  244.     if(bp == NULLBUF){
  245.         /* Nothing left */
  246.         return;
  247.     }
  248.     /* Sneak a peek at the control field. This kludge is necessary because
  249.      * AX.25 lacks a proper protocol ID field between the address and LAPB